package br.com.foxinline.servico;

import br.com.foxinline.generico.ServicoGenerico;
import br.com.foxinline.modelo.*;
import br.com.nordestefomento.jrimum.bopepo.guia.BancoSuportado;
import br.com.nordestefomento.jrimum.bopepo.guia.Guia;
import br.com.nordestefomento.jrimum.bopepo.view.guia.GuiaViewer;
import br.com.nordestefomento.jrimum.domkee.comum.pessoa.id.cprf.CPF;
import br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.*;
import br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.Contribuinte;
import br.com.nordestefomento.jrimum.utilix.DateUtil;
import br.com.nordestefomento.jrimum.utilix.ObjectUtil;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.imageio.ImageIO;
import javax.persistence.Query;
import org.apache.commons.lang.StringUtils;
import org.jrimum.bopepo.pdf.Files;
import org.jrimum.utilix.ClassLoaders;

/**
 *
 * @author nayra
 */
@Stateless
public class ItbiServico extends ServicoGenerico<Itbi> {

    @EJB
    private GrupoBairroServico grupoBairroServico;
    @EJB
    private ConfigItbiServico configItbiServico;
    @EJB
    private ConfigIptuServico configIptuServico;
    @EJB
    private PrefeituraServico prefeituraServico;

    public ItbiServico() {
        super(Itbi.class);
    }

    public List<Itbi> findByImovel(String idImovel) {
        String sql = "SELECT itbi FROM " + Itbi.class.getSimpleName()
                + " itbi JOIN itbi.imovel imovel WHERE itbi.imovel.id = :idImovel and itbi.ativo = true";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("idImovel", Long.parseLong(idImovel));
        return query.getResultList();
    }

    public void gerarItbi(Itbi itbi) throws Exception {
        itbi.setDataGeracao(new Date());
        itbi.setPago(false);

        if (itbi.getId() == null) {
            this.save(itbi);
        } else {
            this.update(itbi);
        }
    }

    public Itbi initItbi(Imovel imovel) {
        ConfigItbi configItbi = configItbiServico.findAll().get(0);
        ConfigIptu configIptu = configIptuServico.findAll().get(0);

        Bairro bairro = imovel.getEnderecoImovel().getBairroDne();

        BigDecimal vm2Bairro = grupoBairroServico.vm2PorBairro(bairro, configItbi);
        BigDecimal vvt = vvt(imovel, vm2Bairro, configIptu.getUfmp());

        Itbi itbi = new Itbi();
        itbi.setImovel(imovel);
        itbi.setUfmp(configIptu.getUfmp());
        itbi.setM2AreaTerreno(imovel.getDimensoes().getAreaTerreno());
        itbi.setVlrM2UfmpTerreno(vm2Bairro.multiply(itbi.getUfmp()).divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP));
        itbi.setVlrTerreno(vvt);
        itbi.setM2AreaEdificacao(imovel.getDimensoes().getAreaTotalEdificacao());
        return itbi;
    }

    //VVT = AI x Vm2
    public BigDecimal vvt(Imovel imovel, BigDecimal vm2, BigDecimal ufmp) {
        BigDecimal areadoTerreno = imovel.getDimensoes().getAreaTerreno();
        return vm2.multiply(areadoTerreno).multiply(ufmp).divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP);
    }

    public void validaConfigItbi() throws Exception {
        List<ConfigItbi> configItbis = configItbiServico.findAll();
        List<ConfigIptu> configIptus = configIptuServico.findAll();

        if (!(configItbis != null && !configItbis.isEmpty())) {
            throw new Exception("Verifique as configurações do ITBI");
        }
        if (!(configIptus != null && !configIptus.isEmpty())) {
            throw new Exception("Verifique as configurações do IPTU");
        }
    }

    public void validaImovel(Imovel imovel) throws Exception {
        if (imovel.getProprietarios().isEmpty()) {
            throw new Exception("Preencha as informações sobre o Proprietário!");
        }
        if (imovel.getDimensoes().getAreaTerreno() == null || imovel.getDimensoes().getAreaTotalEdificacao() == null 
                || imovel.getDimensoes().getAreaTerreno() == null) {
            throw new Exception("Preencha as informações sobre as Dimensões!");
        }

        if (imovel.getEnderecoImovel() == null && !StringUtils.isEmpty(imovel.getEnderecoImovel().getLogradouro())
                && !StringUtils.isEmpty(imovel.getEnderecoImovel().getNumero())
                && imovel.getEnderecoImovel().getBairroDne() == null) {
            throw new Exception("Preencha as informações sobre o Endereço!");
        }
        
        if(grupoBairroServico.findGrupoBairro(imovel.getEnderecoImovel().getBairroDne()).isEmpty()){
            throw new Exception("Adicione o bairro " + imovel.getEnderecoImovel().getBairroDne().getNome() + 
                    " as configurações do ITBI.");
        }
    }

    public void gerarGuia(Itbi itbi) {
        try {
            Proprietario proprietario = itbi.getProprietario();
            Imovel imovel = itbi.getImovel();
            Prefeitura prefeitura = prefeituraServico.findAll().get(0);

            int codFebraban = Integer.parseInt(prefeitura.getCodigoFebraban());
            int numConvenio = Integer.parseInt(prefeitura.getBancoNumeroConvenio());
            String nossoNumero = criarNossoNumero(itbi);

            Endereco endImovel = imovel.getEnderecoImovel();
            String endereco = endImovel.getLogradouro() + ", " + endImovel.getNumero() + " - "
                    + endImovel.getBairroDne().getNome() + " " + (endImovel.getCompl() == null ? "" : endImovel.getCompl());

            NumberFormat nf = NumberFormat.getCurrencyInstance();
            DecimalFormatSymbols s = ((DecimalFormat) nf).getDecimalFormatSymbols();
            s.setCurrencySymbol("");
            s.setGroupingSeparator('.');
            s.setMonetaryDecimalSeparator(',');
            ((DecimalFormat) nf).setDecimalFormatSymbols(s);

            Contribuinte contribuinte = new Contribuinte(proprietario.getNome());
            contribuinte.setCPF(new CPF(proprietario.getCpf()));
            OrgaoRecebedor orgaoRecebedor = new OrgaoRecebedor(prefeitura.getNome(), TipoSeguimento.PREFEITURA);
            orgaoRecebedor.setCodigoDeIdentificacaoFebraban(new CodigoDeIdentificacaoFebraban(codFebraban));

            Anexo logo = prefeituraServico.findAll().get(0).getLogo();
            Image imageOrgaoRecebedor = ImageIO.read(new File(logo.getUrl().concat(logo.getNome())));
            if (ObjectUtil.isNotNull(imageOrgaoRecebedor)) {
                orgaoRecebedor.setImgLogo(imageOrgaoRecebedor);
            }

            Convenio convenio = new Convenio(BancoSuportado.BANCO_DO_BRASIL.create(), numConvenio);
            Arrecadacao arrecadacao = new Arrecadacao(orgaoRecebedor, contribuinte, convenio);
            arrecadacao.setNossoNumero(nossoNumero);
            arrecadacao.setValorDocumento(itbi.getValor().divide(BigDecimal.ONE, 2, RoundingMode.UP));
            arrecadacao.setTipoValorReferencia(TipoValorReferencia.QUANTIDADE_DE_MOEDA_COM_DV_MODULO_10);
            arrecadacao.setDataDoDocumento(itbi.getDataGeracao());
            arrecadacao.setDataDoVencimento(itbi.getDataVencimento());

            Guia guia = new Guia(arrecadacao);
            GuiaViewer guiaViewer = new GuiaViewer(guia);

            File templatePersonalizado = new File(ClassLoaders.getResource("/br/com/foxinline/relatorio/itbi/GuiaTemplate.pdf").getFile());

            if (ObjectUtil.isNotNull(templatePersonalizado)) {
                guia.addTextosExtras("txtNomeContribuinte", itbi.getProprietario().getNome().toUpperCase());
                guia.addTextosExtras("txtImovelEndereco", endereco.toUpperCase());
                guia.addTextosExtras("txtInscImovel", inscricaoEstadual(itbi.getImovel()));
                guia.addTextosExtras("txtControleBaixa", nossoNumero);
                guia.addTextosExtras("txtControleBaixa2", nossoNumero);
                guia.addTextosExtras("txtDataEmissao", DateUtil.FORMAT_DD_MM_YYYY.format(guia.getArrecadacao().getDataDoDocumento()));
                guia.addTextosExtras("txtAreaTerreno", nf.format(itbi.getM2AreaTerreno()));
                guia.addTextosExtras("txtAreaEdificada", nf.format(itbi.getM2AreaEdificacao()));
                guia.addTextosExtras("txtVenalTerreno", nf.format(itbi.getVlrTerreno()));
                guia.addTextosExtras("txtVenalEdificacao", nf.format(itbi.getVlrEdificacao()));
                guia.addTextosExtras("txtVenalImovel", nf.format(itbi.getVlrImovel()));
                nf.setMinimumFractionDigits(4);
                guia.addTextosExtras("txtAliquota", nf.format(itbi.getAliquota()));
                nf.setMinimumFractionDigits(2);
                guia.addTextosExtras("txtTotalReais", nf.format(itbi.getValor()));
                guia.addTextosExtras("txtTotalReais2", nf.format(itbi.getValor()));
                guiaViewer.setTemplate(templatePersonalizado);
            }

            File guiaItbi = guiaViewer.getPdfAsFile("GuiaItbi.pdf");
            RelatorioServico.genReport(Files.fileToBytes(guiaItbi));
        } catch (IOException ex) {
            Logger.getLogger(ItbiServico.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private String inscricaoEstadual(Imovel imovel) {
        String inscCadastral = "";
        DecimalFormat d = new DecimalFormat("");
        d.setMinimumIntegerDigits(2);
        inscCadastral += d.format(imovel.getInscricaoCadastralD() == null ? 0 : imovel.getInscricaoCadastralD()) + ".";
        inscCadastral += d.format(imovel.getInscricaoCadastralS() == null ? 0 : imovel.getInscricaoCadastralS()) + ".";
        d.setMinimumIntegerDigits(3);
        inscCadastral += d.format(imovel.getInscricaoCadastralQuadra() == null ? 0 : imovel.getInscricaoCadastralQuadra()) + ".";
        d.setMinimumIntegerDigits(4);
        d.setDecimalSeparatorAlwaysShown(false);
        inscCadastral += d.format(imovel.getInscricaoCadastralLote() == null ? 0 : imovel.getInscricaoCadastralLote()) + ".";
        inscCadastral = inscCadastral.replace(",", "");
        d.setMinimumIntegerDigits(2);
        inscCadastral += d.format(imovel.getInscricaoCadastralUnid() == null ? 0 : imovel.getInscricaoCadastralUnid());
        return inscCadastral;
    }

    private String criarNossoNumero(Itbi itbi) {
        DecimalFormat d = new DecimalFormat("");
        d.setMinimumIntegerDigits(12);
        String codBaixa = "005" + d.format(itbi.getId()).replace(",", "").replace(".", "") + "00";
        return codBaixa;
    }
}